Use watch to detect new domains and avoid polling for dead domains.
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Tue, 30 Aug 2005 20:02:59 +0000 (20:02 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Tue, 30 Aug 2005 20:02:59 +0000 (20:02 +0000)
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
tools/console/daemon/io.c
tools/console/daemon/io.h
tools/console/daemon/main.c
tools/console/daemon/utils.c

index 2ff922351a2dee6fd84a99d3e07ca7ebbebfa989..e7c023bf304ce54b115705fcd79339fb688f5072 100644 (file)
@@ -215,9 +215,6 @@ static int domain_create_ring(struct domain *dom)
        char *dompath, *path;
        int err;
 
-       dom->page = NULL;
-       dom->evtchn_fd = -1;
-
        asprintf(&path, "/console/%d/domain", dom->domid);
        dompath = xs_read(xs, path, NULL);
        free(path);
@@ -232,28 +229,35 @@ static int domain_create_ring(struct domain *dom)
        if (err)
                goto out;
 
-       dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(),
-                                        PROT_READ|PROT_WRITE, dom->mfn);
        if (dom->page == NULL) {
-               err = EINVAL;
-               goto out;
-       }
-
-       /* Opening evtchn independently for each console is a bit
-        * wastefule, but that's how the code is structured... */
-       err = open("/dev/xen/evtchn", O_RDWR);
-       if (err == -1) {
-               err = errno;
-               goto out;
+               dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(),
+                                                PROT_READ|PROT_WRITE,
+                                                dom->mfn);
+               if (dom->page == NULL) {
+                       err = EINVAL;
+                       goto out;
+               }
        }
-       dom->evtchn_fd = err;
 
-       if (ioctl(dom->evtchn_fd, EVENTCHN_BIND, dom->local_port) == -1) {
-               err = errno;
-               munmap(dom->page, getpagesize());
-               close(dom->evtchn_fd);
-               dom->evtchn_fd = -1;
-               goto out;
+       if (dom->evtchn_fd == -1) {
+               /* Opening evtchn independently for each console is a bit
+                * wastefule, but that's how the code is structured... */
+               err = open("/dev/xen/evtchn", O_RDWR);
+               if (err == -1) {
+                       err = errno;
+                       goto out;
+               }
+               dom->evtchn_fd = err;
+               if (ioctl(dom->evtchn_fd, EVENTCHN_BIND,
+                         dom->local_port) == -1) {
+                       err = errno;
+                       munmap(dom->page, getpagesize());
+                       dom->page = NULL;
+                       close(dom->evtchn_fd);
+                       dom->evtchn_fd = -1;
+                       goto out;
+               }
        }
 
  out:
@@ -281,6 +285,9 @@ static struct domain *create_domain(int domid)
        dom->buffer.max_capacity = 0;
        dom->next = NULL;
 
+       dom->page = NULL;
+       dom->evtchn_fd = -1;
+
        domain_create_ring(dom);
 
        dolog(LOG_DEBUG, "New domain %d", domid);
@@ -290,22 +297,19 @@ static struct domain *create_domain(int domid)
 
 static struct domain *lookup_domain(int domid)
 {
-       struct domain **pp;
-
-       for (pp = &dom_head; *pp; pp = &(*pp)->next) {
-               struct domain *dom = *pp;
+       struct domain *dom;
 
-               if (dom->domid == domid) {
+       for (dom = dom_head; dom; dom = dom->next)
+               if (dom->domid == domid)
                        return dom;
-               } else if (dom->domid > domid) {
-                       *pp = create_domain(domid);
-                       (*pp)->next = dom;
-                       return *pp;
-               }
-       }
 
-       *pp = create_domain(domid);
-       return *pp;
+       dom = create_domain(domid);
+       if (!dom)
+               return NULL;
+       dom->next = dom_head;
+       dom_head = dom;
+
+       return dom;
 }
 
 static void remove_domain(struct domain *dom)
@@ -345,6 +349,20 @@ static void remove_dead_domains(struct domain *dom)
        }
 }
 
+void enum_domains(void)
+{
+       int domid = 1;
+       xc_dominfo_t dominfo;
+       struct domain *dom;
+
+       while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
+               dom = lookup_domain(dominfo.domid);
+               if (dominfo.dying || dominfo.crashed || dominfo.shutdown)
+                       dom->is_dead = true;
+               domid = dominfo.domid + 1;
+       }
+}
+
 static void handle_tty_read(struct domain *dom)
 {
        ssize_t len;
@@ -415,20 +433,28 @@ static void handle_xcs_msg(int fd)
                dolog(LOG_ERR, "read from xcs failed! %m");
                exit(1);
        }
+
+       enum_domains();
 }
 
-static void enum_domains(void)
+static void handle_xs(int fd)
 {
-       int domid = 0;
-       xc_dominfo_t dominfo;
+       char **vec;
+       int domid;
        struct domain *dom;
 
-       while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
-               dom = lookup_domain(dominfo.domid);
-               if (dominfo.dying || dominfo.crashed || dominfo.shutdown)
-                       dom->is_dead = true;
-               domid = dominfo.domid + 1;
+       vec = xs_read_watch(xs);
+       if (!vec)
+               return;
+
+       if (sscanf(vec[0], "/console/%d", &domid) == 1) {
+               dom = lookup_domain(domid);
+               if (dom && (dom->evtchn_fd == -1 || dom->page == NULL))
+                       domain_create_ring(dom);
        }
+
+       xs_acknowledge_watch(xs, vec[1]);
+       free(vec);
 }
 
 void handle_io(void)
@@ -438,7 +464,7 @@ void handle_io(void)
 
        do {
                struct domain *d;
-               struct timeval tv = { 1, 0 };
+               struct timeval tv = { 100, 0 };
                int max_fd = -1;
 
                FD_ZERO(&readfds);
@@ -447,6 +473,9 @@ void handle_io(void)
                FD_SET(xcs_data_fd, &readfds);
                max_fd = MAX(xcs_data_fd, max_fd);
 
+               FD_SET(xs_fileno(xs), &readfds);
+               max_fd = MAX(xs_fileno(xs), max_fd);
+
                for (d = dom_head; d; d = d->next) {
                        if (d->tty_fd != -1) {
                                FD_SET(d->tty_fd, &readfds);
@@ -463,7 +492,9 @@ void handle_io(void)
                }
 
                ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
-               enum_domains();
+
+               if (FD_ISSET(xs_fileno(xs), &readfds))
+                       handle_xs(xs_fileno(xs));
 
                if (FD_ISSET(xcs_data_fd, &readfds))
                        handle_xcs_msg(xcs_data_fd);
index f658bfcea03eb96dafb8d1b7c2b9d2e8f60208a2..8fa04b677566d0a00b58e165b49d34f2b9c67e8a 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef CONSOLED_IO_H
 #define CONSOLED_IO_H
 
+void enum_domains(void);
 void handle_io(void);
 
 #endif
index b37351b898dda5807f00fa36a7d7da4f4be22064..6632ca22306ac289296b7602a96e875df7fe611d 100644 (file)
@@ -85,6 +85,8 @@ int main(int argc, char **argv)
 
        xen_setup();
 
+       enum_domains();
+
        handle_io();
 
        closelog();
index d629b8e086ab915dbc87ed837937f5c13053cdb6..c368c23017547d5d5186fb6f405019ef5d5b714b 100644 (file)
@@ -232,11 +232,16 @@ bool xen_setup(void)
                dolog(LOG_ERR, "xcs virq bind failed.  Possible bug.");
                goto out_close_data;
        }
-       
+
+       if (!xs_watch(xs, "/console", "console")) {
+               dolog(LOG_ERR, "xenstore watch on /console failes.");
+               goto out_close_data;
+       }
+
        return true;
 
  out_close_data:
-       close(xcs_ctrl_fd);
+       close(xcs_data_fd);
        xcs_data_fd = -1;
  out_close_ctrl:
        close(xcs_ctrl_fd);